跳到主要内容

Casbin 的 RBAC 模型

RBAC 模型

ACL 模型在用户和资源都比较少的情况下没什么问题,但是用户和资源量一大,ACL 就会变得异常繁琐。想象一下,每次新增一个用户,都要把他需要的权限重新设置一遍是多么地痛苦。

RBAC(role-based-access-control)模型通过引入角色(role)这个中间层来解决这个问题。每个用户都属于一个角色,例如开发者、管理员、运维等,每个角色都有其特定的权限,权限的增加和删除都通过角色来进行。

这样新增一个用户时,我们只需要给他指派一个角色,他就能拥有该角色的所有权限。修改角色的权限时,属于这个角色的用户权限就会相应的修改。

RBAC 是什么?

RBAC就是一个权限控制模型,这个模型是经过时间沉淀之后,相当通用、成熟且被大众接受认可的一个模型。

RBAC 是 Role Based Access Control 的缩写,是基于角色的访问控制。

一般都是分为

  • 用户(user)
  • 角色(role)
  • 权限(permission)

三个实体,角色(role)和权限(permission)是多对多的关系,用户(user)和角色(role)也是多对多的关系。

用户(user)和权限(permission)之间没有直接的关系,都是通过角色作为代理,才能获取到用户(user)拥有的权限。

提示

一个用户可以拥有若干角色,每一个角色有可以被分配若干权限这样,就构造成“用户-角色-权限” 的授权模型。在这种模型中,用户与角色、角色与权限之间构成了多对多的关系,如下图

在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。

一般情况下,使用5张表就够了,3个实体表,2个关系表,设计如下所示:

casbin 上使用该模型

在 casbin 中使用 RBAC 模型需要在模型文件中添加 role_definition 模块:

[role_definition]
g = _, _

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

g = _,_ 意味着在一个继承关系中有两个当事人,即定义了 用户——角色,角色——角色的映射关系,前者是后者的成员,拥有后者的权限。

然后在匹配器中,我们不需要判断 r.subp.sub 完全相等,只需要使用 g(r.sub, p.sub) 来判断请求主体 r.sub 是否属于 p.sub 这个角色即可。最后我们修改策略文件添加用户——角色定义:

p, admin, data, read
p, admin, data, write
p, developer, data, read
g, dajun, admin
g, lizi, developer
  • dajun 属于 admin 管理员
  • lizi 属于 developer 开发者,使用 g 来定义这层关系。

另外 admin 对数据 data 用 read 和 write 权限,而 developer 对数据 data 只有 read 权限。

package main

import (
"fmt"
"log"

"github.com/casbin/casbin/v2"
)

func check(e *casbin.Enforcer, sub, obj, act string) {
ok, _ := e.Enforce(sub, obj, act)
if ok {
fmt.Printf("%s CAN %s %s\n", sub, act, obj)
} else {
fmt.Printf("%s CANNOT %s %s\n", sub, act, obj)
}
}

func main() {
e, err := casbin.NewEnforcer("./model.conf", "./policy.csv")
if err != nil {
log.Fatalf("NewEnforecer failed:%v\n", err)
}

check(e, "dajun", "data", "read")
check(e, "dajun", "data", "write")
check(e, "lizi", "data", "read")
check(e, "lizi", "data", "write")
}

Reference